home *** CD-ROM | disk | FTP | other *** search
/ Sound Fx / Sound Fx.iso / Software / UNZIPED / MPW181-5 / _SETUP.1 / sparc_obuffer.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-21  |  9.7 KB  |  389 lines

  1. /* sparc_obuffer.cc
  2.  
  3.    Output buffer for Sun SPARC systems written by
  4.    Tobias Bading (bading@cs.tu-berlin.de)
  5.  
  6.    Idea and first implementation for u-law output with fast downsampling by
  7.    Jim Boucher (jboucher@flash.bu.edu)
  8.  
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2 of the License, or
  12.    (at your option) any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #ifdef SPARC
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <sys/ioctl.h>
  32. #include <iostream.h>
  33.  
  34. extern "C" {
  35. #ifdef SunOS5+
  36. #include <sys/audioio.h>
  37. #else
  38. #include <sun/audioio.h>
  39. #endif // SunOS5+
  40. }
  41.  
  42. #ifdef ULAW
  43. #include "ulaw.h"
  44. #endif
  45.  
  46. #ifdef SunOS
  47. extern "C" int ioctl (int, int ...);        // Why...???
  48. #endif
  49.  
  50. #include "args.h"
  51. #include "header.h"
  52. #include "obuffer.h"
  53.  
  54. int SparcObuffer::audio_fd = -1;
  55.  
  56. #ifdef ULAW
  57. SparcObuffer::SparcObuffer (Header *header, MPEG_Args *maplay_args)
  58. #else
  59. SparcObuffer::SparcObuffer (uint32 number_of_channels, MPEG_Args *maplay_args)
  60. #endif
  61. {
  62. #ifndef ULAW
  63. #ifdef DEBUG
  64.   if (!number_of_channels || number_of_channels > MAXCHANNELS)
  65.   {
  66.     cerr << "SparcObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
  67.     exit (1);
  68.   }
  69. #endif
  70. #endif    // !ULAW
  71.  
  72.   if (audio_fd < 0)
  73.   {
  74.     cerr << "Internal error: SparcObuffer::audio_fd has to be initialized\n"
  75.         "by SparcObuffer::class_suitable()!\n";
  76.     exit (1);
  77.   }
  78.  
  79.   audio_info info;
  80.   AUDIO_INITINFO (&info);
  81. #ifdef SunOS4_1_3
  82.   info.output_muted = False;
  83. #endif
  84.   info.play.port = 0;
  85.   if (maplay_args->use_speaker)
  86.     info.play.port |= AUDIO_SPEAKER;
  87.   if (maplay_args->use_headphone)
  88.     info.play.port |= AUDIO_HEADPHONE;
  89. #ifdef SunOS4_1_3
  90.   if (maplay_args->use_line_out)
  91.     info.play.port |= AUDIO_LINE_OUT;
  92. #endif
  93.  
  94. #ifdef ULAW
  95.   bufferp = buffer;
  96.  
  97.   // configure the amd device:
  98.   info.play.encoding = AUDIO_ENCODING_ULAW;
  99.   info.play.precision = 8;
  100.   info.play.channels = 1;
  101.   info.play.sample_rate = 8000;
  102. #else
  103.   channels = number_of_channels;
  104.   for (int i = 0; i < number_of_channels; ++i)
  105.     bufferp[i] = buffer + i;
  106.  
  107.   // configure the dbri device:
  108.   info.play.encoding = AUDIO_ENCODING_LINEAR;
  109.   info.play.precision = 16;
  110.   info.play.channels = channels;
  111.   info.play.sample_rate = maplay_args->MPEGheader->frequency ();
  112. #endif    // !ULAW
  113.  
  114.   if (ioctl (audio_fd, AUDIO_SETINFO, &info))
  115.   {
  116.     perror ("configuration of /dev/audio failed");
  117.     exit (1);
  118.   }
  119. }
  120.  
  121.  
  122. SparcObuffer::~SparcObuffer (void)
  123. {
  124.   ioctl (audio_fd, AUDIO_DRAIN, NULL);
  125.   close (audio_fd);
  126. }
  127.  
  128.  
  129. void SparcObuffer::append (uint32 channel, int16 value)
  130. {
  131. #ifdef ULAW
  132. #ifdef DEBUG
  133.   if (bufferp - buffer >= OBUFFERSIZE >> 1)
  134.   {
  135.     cerr << "SparcObuffer: buffer overflow!\n";
  136.     exit (1);
  137.   }
  138. #endif
  139.  
  140.   // convert 16-bit PCM sample to 8-bit ulaw:
  141.   *bufferp++ = linear2ulaw[value >> 3];
  142. #else
  143. #ifdef DEBUG
  144.   if (channel >= channels)
  145.   {
  146.     cerr << "illegal channelnumber in SparcObuffer::append()!\n";
  147.     exit (1);
  148.   }
  149.   if (bufferp[channel] - buffer >= OBUFFERSIZE)
  150.   {
  151.     cerr << "SparcObuffer: buffer overflow!\n";
  152.     exit (1);
  153.   }
  154. #endif
  155.  
  156.   *bufferp[channel] = value;
  157.   bufferp[channel] += channels;
  158. #endif    // !ULAW
  159. }
  160.  
  161. void SparcObuffer::write_buffer (int)
  162. {
  163. #ifdef ULAW
  164.   int length = (int)((char *)bufferp - (char *)buffer);
  165. #else
  166.   int length = (int)((char *)*bufferp - (char *)buffer);
  167. #endif
  168.   if (write (audio_fd, (char *)buffer, length) != length)
  169.   {
  170.     perror ("write to /dev/audio failed");
  171.     exit (1);
  172.   }
  173. #ifdef ULAW
  174.   bufferp = buffer;
  175. #else
  176.   for (int i = 0; i < channels; ++i)
  177.     bufferp[i] = buffer + i;
  178. #endif
  179. }
  180.  
  181. #ifdef SEEK_STOP
  182. void SparcObuffer::clear_buffer(void)
  183. {
  184. }
  185.  
  186. void SparcObuffer::set_stop_flag(void)
  187. {
  188. }
  189. #endif // SEEK_STOP
  190.  
  191. int SparcObuffer::open_audio_device (void)
  192. {
  193.   int fd;
  194.  
  195.   if ((fd = open ("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0)
  196.     if (errno == EBUSY)
  197.     {
  198.       cerr << "Sorry, the audio device is busy!\n";
  199.       exit (1);
  200.     }
  201.     else
  202.     {
  203.       perror ("can't open /dev/audio for writing");
  204.       exit (1);
  205.     }
  206.  
  207.   // turn NDELAY mode off:
  208.   int flags;
  209.   if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
  210.   {
  211.     perror ("fcntl F_GETFL on /dev/audio failed");
  212.     exit (1);
  213.   }
  214.   flags &= ~O_NDELAY;
  215.   if (fcntl (fd, F_SETFL, flags) < 0)
  216.   {
  217.     perror ("fcntl F_SETFL on /dev/audio failed");
  218.     exit (1);
  219.   }
  220.   return fd;
  221. }
  222.  
  223.  
  224. #ifdef Solaris
  225. void SparcObuffer::get_device_type (int fd, audio_device *devtype)
  226. {
  227.   if (ioctl (fd, AUDIO_GETDEV, devtype))
  228.   {
  229.     perror ("ioctl AUDIO_GETDEV on /dev/audio");
  230.     exit (1);
  231.   }
  232. }
  233. #else
  234. int SparcObuffer::get_device_type (int fd)
  235. {
  236. #ifdef AUDIO_GETDEV
  237.   int devtype;
  238.   if (ioctl (fd, AUDIO_GETDEV, &devtype))
  239.   {
  240.     perror ("ioctl AUDIO_GETDEV on /dev/audio");
  241.     exit (1);
  242.   }
  243.   return devtype;
  244. #else
  245.   cerr << "SparcObuffer::get_device_type(): AUDIO_GETDEV ioctl not available!\n";
  246.   return -1;
  247. #endif
  248. }
  249. #endif    // !Solaris
  250.  
  251.  
  252. #ifdef ULAW
  253. BOOL SparcObuffer::class_suitable (uint32 number_of_channels, BOOL force_amd)
  254. #else
  255. BOOL SparcObuffer::class_suitable (void)
  256. #endif
  257. {
  258. #ifdef ULAW
  259.   if (number_of_channels > 1)
  260.   {
  261.     cerr << "Your audio hardware cannot handle more than one audio channel.\n"
  262.         "Please use the option -l or -r for stereo streams.\n";
  263.     return False;
  264.   }
  265. #endif
  266.  
  267.   // check for the dbri audio device:
  268.   audio_fd = open_audio_device ();
  269.  
  270. #ifdef ULAW
  271.   if (force_amd)
  272.     return True;
  273. #endif
  274.  
  275. #ifdef Solaris
  276.   audio_device devtype;
  277.   get_device_type (audio_fd, &devtype);
  278. # ifdef ULAW
  279.     if (!strcmp (devtype.name, "SUNW,am79c30"))
  280.       return True;
  281.     else if (!strcmp (devtype.name, "SUNW,dbri"))
  282.     {
  283.       cerr << "Your machine can produce CD-quality audio output,\n"
  284.           "but this binary was compiled for 8 kHz u-law ouput. (telephone quality)\n"
  285.           "Please recompile it without the ULAW define in COMPILERFLAGS.\n"
  286.           "(or use the -amd option to use this binary with low-quality output)\n";
  287.       close (audio_fd);
  288.       return False;
  289.     }
  290. # else
  291.     if (!strcmp (devtype.name, "SUNW,dbri"))
  292.       return True;
  293.     else if (!strcmp (devtype.name, "SUNW,am79c30"))
  294.     {
  295.       cerr << "Your machine can produce 8 kHz u-law audio output only,\n"
  296.           "but this binary was compiled for CD-quality output.\n"
  297.           "Please recompile it with ULAW defined in COMPILERFLAGS\n"
  298.           "or use it in stdout mode as an decoder only.\n";
  299.       close (audio_fd);
  300.       return False;
  301.     }
  302. # endif
  303. #else
  304.   // !Solaris
  305. # ifdef SunOS4_1_1
  306.     // no AUDIO_GETDEV under SunOS 4.1.1, so we have to assume that there is
  307.     // an amd device attached to /dev/audio
  308. #   ifdef ULAW
  309.       return True;
  310. #   else
  311.       cerr << "Your machine can produce 8 kHz u-law audio output only,\n"
  312.           "but this binary was compiled for CD-quality output.\n"
  313.           "Please recompile it with ULAW defined in COMPILERFLAGS\n"
  314.           "or use it in stdout mode as an decoder only.\n";
  315.       close (audio_fd);
  316.       return False;
  317. #   endif    // !ULAW
  318. # else
  319.     // SunOS 4.1.3
  320.     int device_type = get_device_type (audio_fd);
  321. #   ifdef ULAW
  322.       if (device_type == AUDIO_DEV_AMD)
  323.     return True;
  324.       else if (device_type == AUDIO_DEV_SPEAKERBOX)
  325.       {
  326.     cerr << "Your machine can produce CD-quality audio output,\n"
  327.         "but this binary was compiled for 8 kHz u-law ouput. (telephone quality)\n"
  328.         "Please recompile it without the ULAW define in COMPILERFLAGS.\n"
  329.         "(or use the -amd option to use this binary with low-quality output)\n";
  330.     close (audio_fd);
  331.     return False;
  332.       }
  333. #   else
  334.       if (device_type == AUDIO_DEV_SPEAKERBOX)
  335.     return True;
  336.       else if (device_type == AUDIO_DEV_AMD)
  337.       {
  338.     cerr << "Your machine can produce 8 kHz u-law audio output only,\n"
  339.         "but this binary was compiled for CD-quality output.\n"
  340.         "Please recompile it with ULAW defined in COMPILERFLAGS\n"
  341.         "or use it in stdout mode as an decoder only.\n";
  342.     close (audio_fd);
  343.     return False;
  344.       }
  345. #   endif    // !ULAW
  346. # endif    // !SunOS4_1_1
  347. #endif    // !Solaris
  348.  
  349. #ifndef SunOS4_1_1
  350.   close (audio_fd);
  351.   cerr << "Sorry, I don't recognize your audio device.\n"
  352. # ifdef ULAW
  353.       "Please try the -amd option or use the stdout mode.\n";
  354. # else
  355.       "Please use the stdout mode.\n";
  356. # endif
  357.   return False;
  358. #endif // SunOS4_1_1
  359. }
  360.  
  361. Obuffer *create_obuffer(MPEG_Args *maplay_args)
  362. {
  363.   Obuffer *buffer;
  364.  
  365.   enum e_mode mode = maplay_args->MPEGheader->mode();
  366.   enum e_channels which_channels = maplay_args->which_c;
  367.  
  368. #ifdef ULAW
  369.   BOOL force_amd = maplay_args->force_amd;
  370.  
  371.   if (SparcObuffer::class_suitable ((mode == single_channel ||
  372.                                      which_channels != both) ? 1 : 2,
  373.                                      force_amd))     // amd device available?
  374.      buffer = new SparcObuffer (maplay_args);
  375. #else
  376.   if (SparcObuffer::class_suitable())               // dbri device available?
  377.      if (mode == single_channel || which_channels != both)
  378.         buffer = new SparcObuffer (1, maplay_args);
  379.      else
  380.         buffer = new SparcObuffer (2, maplay_args);
  381. #endif // ULAW
  382.   else
  383.      return(NULL);
  384.  
  385.   return(buffer);
  386. }
  387.  
  388. #endif    // SPARC
  389.